package heap

import (
	"fmt"
	"jvm/classfile"
)

type Constant interface{}

type ConstantPool struct {
	class  *Class
	consts []Constant
}

func newConstantPool(class *Class, cfCp classfile.ConstantPool) *ConstantPool {
	cpCount := len(cfCp)
	consts := make([]Constant, cpCount)
	rtCp := &ConstantPool{class: class, consts: consts}
	for i := 1; i < cpCount; i++ {
		cpInfo := cfCp[i]
		switch cp := cpInfo.(type) {
		case *classfile.ConstantIntegerInfo:
			consts[i] = cp.Value()
		case *classfile.ConstantFloatInfo:
			consts[i] = cp.Value()
		case *classfile.ConstantLongInfo:
			consts[i] = cp.Value()
			i++
		case *classfile.ConstantDoubleInfo:
			consts[i] = cp.Value()
			i++
		case *classfile.ConstantStringInfo:
			consts[i] = cp.String()
		case *classfile.ConstantClassInfo:
			consts[i] = newClassRef(rtCp, cp)
		case *classfile.ConstantFieldRefInfo:
			consts[i] = newFieldRef(rtCp, cp)
		case *classfile.ConstantMethodRefInfo:
			consts[i] = newMethodRef(rtCp, cp)
		case *classfile.ConstantInterfaceMethodRefInfo:
			consts[i] = newInterfaceMethodRef(rtCp, cp)
		default:
			// todo
		}
	}

	return rtCp
}

func (cp *ConstantPool) GetConstant(index uint) Constant {
	if c := cp.consts[index]; c != nil {
		return c
	}
	panic(fmt.Sprintf("No constants at index %d", index))
}
